/* vie.c */

#include <stdlib.h>
#include <unistd.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include "structs.h"
#include "ui.h"
#include "buffer.h"
#include "window.h"
#include "vie.h"
#include "undo.h"
#include "exbuf.h"
#include "fileio.h"
#include "cmdbuf.h"
#include "command.h"
#include "cmdmap.h"

static int key_recieved_command( int );
static int key_recieved_insert( int );
static int key_recieved_ex( int );


static int increase_start_line(void);
static int decrease_start_line(void);

static int parse_ex_command(const char* raw, char *cmd, char *arg1, int *arg2);

static int init_attribute(void);

static void sig_win_ch(int);	//signal handler

#define KEY_ESC 27
#define KEY_CARRIAGE 10
#define KEY_TAB '\t'

static cmd_buf_t cmd_buf;
static ex_buf_t ex_buf;

int run(){
	int key;
	/*
	keypad(stdscr,TRUE);
	cbreak();
	noecho();
	*/
	while((key=getch())){
		edit_modes[current_mode].key_recieved(key);
	}
	return OK;
}

int init_vie(int fc, char *fn[]){
	if(fc <= 0){
		window_create_window("");
		buf_create_buf(0);
		current_window->is_saved = TRUE;
	}else{
		int i;
		for(i=0;i<fc;i++){
			window_create_window(fn[i]);
			if(OK != file_open(fn[i])){
				if(fc != 1){
					fprintf(stderr, "Invalid file path: %s", fn[i]);
					exit_vie(0);
				}else{
					buf_create_buf(0);
					current_window->is_saved = TRUE;
				}
			}
			current_window->is_saved = TRUE;
		}
	}
	//init buffer infomaiton
	init_buf();
	//init command map
	init_command();
	//init attributes
	init_attribute();
	//register signal handler
	if(signal(SIGWINCH, sig_win_ch) == SIG_ERR){
		fputs("Cannot register signal handler!", stderr);
		exit_vie(-1);
	}
	edit_modes[MODE_COMMAND].key_recieved = key_recieved_command;
	edit_modes[MODE_INSERT].key_recieved = key_recieved_insert;
	edit_modes[MODE_EX].key_recieved = key_recieved_ex;
	switch_mode(MODE_COMMAND,TRUE);
	return OK;
}

int exit_vie(int exit_code){
	end_command();
	end_screen();
	exit(exit_code);
}

int switch_mode(int mode, int enforce){
	if(mode >= MODE_NUM)
		return -1;
	if(current_mode == mode)
		if(!enforce)
			return OK;
	current_mode = mode;
	viescr.edit_mode = mode;

	if(current_mode == MODE_COMMAND){
	}else if(current_mode == MODE_INSERT){
	}else if(current_mode == MODE_EX){
		//reset the buf
		ex_buf.len = 0;
		ex_buf.cursor_pos = 0;
	}
	// do switch work;
	update_screen();	
	return OK;
}



static int key_recieved_command(int key){
	int processed = TRUE;
	switch(key){
	/*
	case 'i':case 'I':
		switch_mode(MODE_INSERT,TRUE);
		break;
	case ':':
		switch_mode(MODE_EX,TRUE);
		break;
	case 'u':
		exec_undo();
		update_screen();
		break;
	case '.':
	    exec_redo();
	    update_screen();
	    break;
	    */
	case 'q':
		exit_vie(0);
		break;
	case KEY_LEFT:
		key_left();
		break;
	case KEY_RIGHT:
		key_right();
		break;
	case KEY_UP:
		key_up();
		break;
	case KEY_DOWN:
		key_down();
		break;
	case KEY_END:
		key_end();
		break;
	case KEY_HOME:
		key_beg();
		break;
	case KEY_PPAGE:
		key_page_up();
		break;
	case KEY_NPAGE:
		key_page_down();
		break;
	case KEY_REPLACE:
		key_insert();
		break;
	case KEY_ESC:
		cmd_buf_reset(&cmd_buf);
		break;
	default:
		processed = FALSE;
	}
	//add the key to command buffer
	if(processed){
		cmd_buf_reset(&cmd_buf);
	}else{
		if(cmd_buf_add_key(&cmd_buf, key)==0){	//add key successfullly
			
			//process the command
			val_t func_ptr = cmd_command_find(cmd_buf.cmd);
			if(func_ptr != NULL){	//process the command
				func_ptr(NULL, cmd_buf.arg_value);
				cmd_buf_reset(&cmd_buf);
			}
		}else{
			//do nothing
		}
	}
	update_screen();
	return OK;
}

static int key_recieved_insert(int key){
	mvprintw(LINES-1,60, "%d\t%c", key,key);
	if(key == KEY_ESC ){
		switch_mode(MODE_COMMAND,TRUE);
		return OK;
	}else if(isprint(key)){
		buf_insertc(viescr.cursor_pos.buf, (char)key, viescr.cursor_pos.offset);
		viescr.cursor_pos.offset ++;
		cursor_right();
	}else{
		switch(key){
		case KEY_CARRIAGE:
			buf_create_buf(viescr.cursor_pos.offset);
			viescr.cursor_pos.buf = current_window->buf;
			viescr.cursor_pos.offset = 0;
			cursor_move_absolute(viescr.cursor_pos.line + 1,0);
			if(VIE_ATTRIBUTE_AUTOINDENT){
				int tab_count = 0;
				buf_t * prev_buf = buf_prev(current_window->buf);
				while(prev_buf->data[tab_count ++] == '\t'){	//count tabs
					buf_inserts(current_window->buf, "\t", viescr.cursor_pos.offset ++);
				}
				roll_screen();
			}
			break;
		case KEY_BACKSPACE:
			if(viescr.cursor_pos.offset ==0 ){
				buf_delete_buf(current_window->buf);
				roll_screen();
			}else{
				buf_delete(current_window->buf,viescr.cursor_pos.offset-1,viescr.cursor_pos.offset);
				viescr.cursor_pos.offset --;
				cursor_left();
			}
			break;
		case KEY_DC:
			if(viescr.cursor_pos.offset < current_window->buf->len ){
				buf_delete(current_window->buf,viescr.cursor_pos.offset, viescr.cursor_pos.offset+1);
			}else{
				if(buf_next(current_window->buf) != NULL){
					buf_delete_buf(buf_next(current_window->buf));
				}
			}
			break;
		case KEY_TAB:
			buf_insertc(viescr.cursor_pos.buf, (char)key, viescr.cursor_pos.offset);
			viescr.cursor_pos.offset ++;
			cursor_right();
			break;
		case KEY_LEFT:
			key_left();
			break;
		case KEY_RIGHT:
			key_right();
			break;
		case KEY_UP:
			key_up();
			break;
		case KEY_DOWN:
			key_down();
			break;
		case KEY_END:
			key_end();
			break;
		case KEY_HOME:
			key_beg();
			break;
		case KEY_PPAGE:
			key_page_up();
			break;
		case KEY_NPAGE:
			key_page_down();
			break;
		case KEY_REPLACE:
			key_insert();
			break;
		}

	}
	update_screen();
	return OK;
}

static int key_recieved_ex(int key){
	static char cmd_buffer[256];
	static char arg_buffer[256];
	
	int processed = FALSE;

	if(key == KEY_ESC ){
		//reset the buf
		ex_buf.len =0;
		ex_buf.cursor_pos = 0;
		//
		switch_mode(MODE_COMMAND,TRUE);
	}
	else{
	       if( ex_buf_add_key(&ex_buf, key) == EX_OK){
	       		// deal with the command.
	       		int force = FALSE;
			if(OK == parse_ex_command(ex_buf.data, cmd_buffer, arg_buffer,&force)){
				//process the command
				val_t func_ptr = ex_command_find(cmd_buffer);
				if(func_ptr != NULL){	//process the command
					func_ptr(arg_buffer, force);
					cmd_buf_reset(&cmd_buf);
					processed = TRUE;
					switch_mode(MODE_COMMAND, TRUE);
					return OK;
				}else{
					state_area_show_error("Invalid command!");
				}

			}else{
				state_area_show_error("Invalid command!");
			}
			//reset the buf
			ex_buf.len = 0;
			ex_buf.cursor_pos = 0;
			ex_buf.data[0]='\0';
	       }
	       if(!processed){
	       		update_state_area_ex(ex_buf.data, ex_buf.cursor_pos);
	       }
	}
      	update_screen();
	move(LINES-1, ex_buf.cursor_pos+1);
	refresh();
	return OK;
}

/* init the file buffer */ 

int init_buf(){
	buf_to_head();
	viescr.start_line = 0;
	viescr.start_buf = current_window->buf;
	int line_count = LINES - 1;
	line_count = line_count;
	viescr.cursor_pos.buf = current_window->buf;
	viescr.cursor_pos.offset = 0;
	viescr.cursor_pos.line = 0;
	viescr.cursor_pos.col = 0;
	return OK;
}


/* functions used to adjust the cursor position */

int cursor_left(){
	
	int x = viescr.cursor_pos.col;
	int y = viescr.cursor_pos.line;
	int x_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset) % VIE_COLS;
	if(x_offset >= x){
		x = x_offset;
		y--;
	}else{
		x = x_offset;
	}
	if(x < 0){
		x = VIE_COLS + x;
		y --;
		if(y < 0){
			y = 0;
			decrease_start_line();
		}
	}
	viescr.cursor_pos.col = x;
	viescr.cursor_pos.line = y;
	return OK;
}

int cursor_right(){
	int x_shift = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset) - tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset-1);
	int x = viescr.cursor_pos.col + x_shift;
	int y = viescr.cursor_pos.line;
	if(x >= VIE_COLS){
		x = x % VIE_COLS;
		y ++;
		if(y >= LINES -1){
			y = LINES -2;
			increase_start_line();
		}
	}
	viescr.cursor_pos.col = x;
	viescr.cursor_pos.line = y;
	return OK;
}
/*
static int cursor_up(){
	int y = viescr.cursor_pos.line -1;
	if(y < 0){
		y = 0;
		decrease_start_line();
	}
	viescr.cursor_pos.line = y;
	return OK;
}



static int cursor_down(){
	int y = viescr.cursor_pos.line +1;
	if(y >= LINES - 1){
		y = LINES -2;
		increase_start_line();
	}
	viescr.cursor_pos.line = y;
	return OK;
}

static int cursor_move(int y, int x){
	y += viescr.cursor_pos.line;
	x += viescr.cursor_pos.col;
	while( y < 0 ){
		y++;
		decrease_start_line();
	}
	while( y >= LINES -1 ){
		y--;
		increase_start_line();
	}
	viescr.cursor_pos.col = x;
	viescr.cursor_pos.line = y;
	return OK;
}
*/

int cursor_move_absolute(int y, int x){
	while( y < 0 ){
		y++;
		decrease_start_line();
	}
	while( y >= LINES -1 ){
		y--;
		increase_start_line();
	}
	viescr.cursor_pos.col = x;
	viescr.cursor_pos.line = y;
	return OK;
}

static int increase_start_line(){
	viescr.start_line ++;
	if( viescr.start_line > tabmap_get_actual_len(viescr.start_buf->tabmap) / VIE_COLS){ // go to next buf
		if(buf_next(viescr.start_buf) != NULL){
			viescr.start_buf = buf_next(viescr.start_buf);
			viescr.start_line = 0;
		}else{
			viescr.start_line --;
			return -1;
		}
	}
	return OK;
}

static int decrease_start_line(){
	viescr.start_line --;
	if( viescr.start_line < 0 ){ // go to prev buf
		if(buf_prev(viescr.start_buf) != NULL){
			viescr.start_buf = buf_prev(viescr.start_buf);
			viescr.start_line = tabmap_get_actual_len(viescr.start_buf->tabmap) / VIE_COLS;
		}else{
			viescr.start_line ++;
			return -1;
		}		
	}
	return OK;
}


int key_left(){
	if(viescr.cursor_pos.offset > 0){
		viescr.cursor_pos.offset --;
		cursor_left();
	}
	/*
	else{
		//go the the prev buffer
		if(buf_prev(current_window->buf)!=NULL){
			buf_current_prev();
			viescr.cursor_pos.buf = current_window->buf;
			viescr.cursor_pos.offset = current_window->buf->len -1;
		}
		cursor_left();
	}*/
	return OK;
}

int key_right(){
	if(viescr.cursor_pos.offset < current_window->buf->len ){
		viescr.cursor_pos.offset ++;
		cursor_right();
	}
	return OK;
}

int key_up(){
	int actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap,viescr.cursor_pos.offset);
	if( actual_cursor_offset>= VIE_COLS){
		int curr_actual_cursor_offset = 0;
		viescr.cursor_pos.offset = tabmap_get_logical_offset(current_window->buf->tabmap, actual_cursor_offset - VIE_COLS);
		curr_actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
		if(actual_cursor_offset /VIE_COLS - curr_actual_cursor_offset/VIE_COLS != 1){
			viescr.cursor_pos.offset ++;
			curr_actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
		}
		cursor_move_absolute(viescr.cursor_pos.line - 1, curr_actual_cursor_offset % VIE_COLS);
	}else{	//go to the prev buffer
		if(buf_prev(current_window->buf)!=NULL){
			int prev_line_offset;
			int last_line_offset;
			int line_count;
			int cursor_offset_x;
			int actual_len;
			buf_current_prev();
			viescr.cursor_pos.buf = current_window->buf;
			//calculate the offset
			prev_line_offset = viescr.cursor_pos.col;
			actual_len = tabmap_get_actual_len(current_window->buf->tabmap);
			line_count = actual_len/VIE_COLS +1;
			last_line_offset = actual_len % VIE_COLS;
			if(prev_line_offset >= last_line_offset){
				viescr.cursor_pos.offset = current_window->buf->len;
				cursor_offset_x = last_line_offset;
			}else{
				int actual_offset = actual_len / VIE_COLS * VIE_COLS + prev_line_offset;
				int curr_actual_cursor_offset = 0;
				viescr.cursor_pos.offset = tabmap_get_logical_offset(current_window->buf->tabmap, actual_offset);
				curr_actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
				if(actual_offset /VIE_COLS != curr_actual_cursor_offset/VIE_COLS){
					viescr.cursor_pos.offset ++;
					curr_actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
				}
				cursor_offset_x = curr_actual_cursor_offset % VIE_COLS;
			}
			cursor_move_absolute(viescr.cursor_pos.line-1, cursor_offset_x);
		}
	}
	return OK;
}

int key_down(){
	int actual_len = tabmap_get_actual_len(current_window->buf->tabmap);
	int actual_cursor_offset = tabmap_get_actual_offset(current_window->buf->tabmap,viescr.cursor_pos.offset);
	if(actual_len - actual_cursor_offset >= VIE_COLS){
		int temp_offset;
		viescr.cursor_pos.offset = tabmap_get_logical_offset(current_window->buf->tabmap, actual_cursor_offset + VIE_COLS );
		temp_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
		if(temp_offset/VIE_COLS == actual_cursor_offset/VIE_COLS){
			viescr.cursor_pos.offset ++;
			temp_offset = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset);
		}
		cursor_move_absolute(viescr.cursor_pos.line + 1, temp_offset%VIE_COLS);
	}else if(actual_len/VIE_COLS > actual_cursor_offset/VIE_COLS){
		viescr.cursor_pos.offset = current_window->buf->len;
		cursor_move_absolute(viescr.cursor_pos.line + 1, actual_len % VIE_COLS);
		
	}else{	//go to the next buffer
		if(buf_next(current_window->buf)!=NULL){
			int prev_last_line_offset = actual_cursor_offset % VIE_COLS;
			int actual_len;
			buf_current_next();
			actual_len = tabmap_get_actual_len(current_window->buf->tabmap);
			viescr.cursor_pos.buf = current_window->buf;
			//calculate the offset
			if(actual_len <= prev_last_line_offset){
				viescr.cursor_pos.offset = current_window->buf->len;
				cursor_move_absolute(viescr.cursor_pos.line + 1, actual_len % VIE_COLS);
			}else{
				viescr.cursor_pos.offset = tabmap_get_logical_offset(current_window->buf->tabmap, prev_last_line_offset);
				cursor_move_absolute(viescr.cursor_pos.line + 1, tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset) %VIE_COLS);
			}
		}
	}
	return OK;
}

int key_page_down(){
	buf_t * itr;
	int line_count = 0;
	for(itr = viescr.start_buf; itr != NULL; itr = buf_next(itr)){
		if(itr == viescr.start_buf){
			line_count = tabmap_get_actual_len(viescr.start_buf->tabmap) / VIE_COLS - viescr.start_line;
		}else{
			line_count += tabmap_get_actual_len(itr->tabmap) / VIE_COLS + 1;
		}
	
		if(line_count >= LINES - 1){
			int logical_offset;
			int actual_offset;
			viescr.start_buf = itr;
			current_window->buf = viescr.start_buf;
			viescr.start_line = line_count - LINES + 1;
			logical_offset = tabmap_get_logical_offset(current_window->buf->tabmap, viescr.start_line * VIE_COLS);
			actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, logical_offset);
			if((actual_offset / VIE_COLS ) < viescr.start_line){
				logical_offset ++;
				actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, logical_offset);
			} 
			viescr.cursor_pos.line = 0;
			viescr.cursor_pos.col = actual_offset % VIE_COLS;
			viescr.cursor_pos.offset = logical_offset;
			break;
		} 
	}

	return OK;
}

int key_page_up(void){
	buf_t * itr;
	int line_count = 0;
	for(itr = viescr.start_buf; itr != NULL; itr = buf_prev(itr)){
		if(itr == viescr.start_buf){
			line_count = viescr.start_line;
		}else{
			line_count += tabmap_get_actual_len(itr->tabmap) / VIE_COLS + 1;
		}
	
		if(line_count >= LINES - 1){
			int logical_offset;
			int actual_offset;
			viescr.start_buf = itr;
			current_window->buf = viescr.start_buf;
			viescr.start_line = line_count - LINES + 1;
			logical_offset = tabmap_get_logical_offset(current_window->buf->tabmap, viescr.start_line * VIE_COLS);
			actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, logical_offset);
			if((actual_offset / VIE_COLS ) < viescr.start_line){
				logical_offset ++;
				actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, logical_offset);
			} 
			viescr.cursor_pos.line = 0;
			viescr.cursor_pos.col = actual_offset % VIE_COLS;
			viescr.cursor_pos.offset = logical_offset;
			break;
		} 
	}

	return OK;
}

int key_end(void){
	int prev_offset_line = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset)/VIE_COLS ;
	int actual_len = tabmap_get_actual_len(current_window->buf->tabmap);
	int curr_offset_line = actual_len /VIE_COLS ;

	
	int y = viescr.cursor_pos.line + (curr_offset_line - prev_offset_line);
	int x = actual_len % VIE_COLS;
	viescr.cursor_pos.offset = current_window->buf->len;
	cursor_move_absolute(y,x);
	return OK;
}

int key_beg(void){
	int prev_offset_line = tabmap_get_actual_offset(current_window->buf->tabmap, viescr.cursor_pos.offset)/VIE_COLS;
	int y = viescr.cursor_pos.line + (0 - prev_offset_line);
	int x = 0;
	viescr.cursor_pos.offset = 0;
	cursor_move_absolute(y,x);
	return OK;
}

int key_insert(void){
	return OK;
}


int roll_screen(){
	int done  = FALSE;

	if(current_window->buf == viescr.start_buf){
		int actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, current_window->buf->last_modified_pos);
		int cursor_line = actual_offset / VIE_COLS;
		if(cursor_line < viescr.start_line ){
			viescr.start_line = cursor_line;
			viescr.cursor_pos.line = 0;
			viescr.cursor_pos.col = actual_offset % VIE_COLS;
		}else{
			if(cursor_line - viescr.start_line <= LINES -1){
				viescr.cursor_pos.line = cursor_line - viescr.start_line;
				viescr.cursor_pos.col = actual_offset % VIE_COLS;
			}else{
				viescr.start_line = cursor_line - LINES + 2;
				viescr.cursor_pos.line = cursor_line - viescr.start_line;
				viescr.cursor_pos.col = actual_offset % VIE_COLS;
			}
		}
		done = TRUE;
	}
	
	if(!done){	//look for the start_buf before current_window->buf
		buf_t * itr = current_window->buf;
		int start_line_count = tabmap_get_actual_len(viescr.start_buf->tabmap) / VIE_COLS +1 - viescr.start_line;	//visible line count of start_buf
		 
		int curr_actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, current_window->buf->last_modified_pos);
		int line_count = curr_actual_offset / VIE_COLS + 1;
		while( (itr = buf_prev(itr) )!= NULL){
			if(itr == viescr.start_buf){
				line_count +=start_line_count;
				if(line_count <= LINES -1){	// No need to roll the screen
					viescr.cursor_pos.line = line_count -1;
					viescr.cursor_pos.col = curr_actual_offset % VIE_COLS;
					done = TRUE;
				}else{		//roll the screen and put the cursor at the last line

					buf_t * itrr = NULL;
					int ln_cnt = 0;
					for(itrr = current_window->buf; itrr != NULL; itrr = buf_prev(itrr)){
						if(itrr == current_window->buf){
							ln_cnt = curr_actual_offset / VIE_COLS + 1;
						}else{
							ln_cnt += tabmap_get_actual_len(itrr->tabmap) / VIE_COLS + 1;
						}
						if(ln_cnt >= LINES - 1){
							viescr.start_buf = itrr;
							viescr.start_line = ln_cnt - LINES + 1;
							viescr.cursor_pos.line = LINES - 2;
							viescr.cursor_pos.col = curr_actual_offset % VIE_COLS;
							break;
						} 
					}
					
					/*
					int offset_line_count = curr_actual_offset / VIE_COLS +1;
					viescr.start_buf = current_window->buf;
					if(offset_line_count <= LINES -1){
						viescr.start_line = 0;
						viescr.cursor_pos.line = offset_line_count -1;
						viescr.cursor_pos.col = curr_actual_offset % VIE_COLS;
					}else{
						viescr.start_line = offset_line_count -1;
						viescr.cursor_pos.line = 0;
						viescr.cursor_pos.col = curr_actual_offset % VIE_COLS;
					}*/
				}
				done = TRUE;
				break;
			}else{
				line_count += tabmap_get_actual_len(itr->tabmap) / VIE_COLS +1;
			}
		}
	}
	
	if(!done){
		int actual_offset = tabmap_get_actual_offset(current_window->buf->tabmap, current_window->buf->last_modified_pos);
		int offset_line_count = actual_offset / VIE_COLS +1;
		viescr.start_buf = current_window->buf;
		if(offset_line_count <= LINES -1){
			viescr.start_line = 0;
			viescr.cursor_pos.line = offset_line_count -1;
			viescr.cursor_pos.col = actual_offset % VIE_COLS;
		}else{
			viescr.start_line = offset_line_count - LINES + 1;
			viescr.cursor_pos.line = LINES - 2;
			viescr.cursor_pos.col = actual_offset % VIE_COLS;
		}
	}
	viescr.cursor_pos.buf = current_window->buf;
	viescr.cursor_pos.offset = current_window->buf->last_modified_pos;
	return OK;
}

int parse_ex_command(const char *raw_cmd, char *cmd, char *arg1, int * arg2){
	int index;
	char * ptr;
	if(raw_cmd[0] == '/' || raw_cmd[0] == '%'){
		strncpy(cmd, raw_cmd, 1);
		cmd[1] = '\0';
		strcpy(arg1, raw_cmd + 1);
		return OK;
	} 
	ptr= strstr(raw_cmd, " ");
	if(ptr == NULL){
		int len;
		strcpy(cmd, raw_cmd);
		len = strlen(cmd);
		if(cmd[len -1] == '!'){
			cmd[len -1] = '\0';
			*arg2 = 1;
		}
		return 0;
	}else if (ptr == raw_cmd){
		return -1;
	}else{
		int len;
		index = ptr - raw_cmd;
		strncpy(cmd, raw_cmd, index);
		cmd[index] = '\0';
		
		len = strlen(cmd);
		if(cmd[len -1] == '!'){
			cmd[len -1] = '\0';
			*arg2 = 1;
		}
		
		strcpy(arg1, raw_cmd + index + 1);
		return 0;
	}		
}


static int init_attribute(){
	VIE_ATTRIBUTE_NUMBER = 0;
	VIE_ATTRIBUTE_HIGHLIGHT = 0;
	VIE_ATTRIBUTE_AUTOINDENT = 0;
	return OK;
}

static void sig_win_ch(int sig){
	window_changed();
}
